
package com.servequake.truemusic.applet;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import java.util.*;
import java.net.*;
import java.io.*;


import javazoom.jl.player.advanced.AdvancedPlayer;


public class AppletAudio implements Runnable
{
	static Object loadlock = new Object();  //ensure one-at-a-time loading


	AppletAudio me = this;

	byte[] buffer;

	String title="";
	String artist="";
	URL resource;

	volatile Thread runner;

	boolean loading = true;

	AppletAudio(String title, String artist, URL resource)
	{
		this.title = title;
		this.artist = artist;
		this.resource = resource;

		new LoadThread().start();
	}

	class LoadThread extends Thread
	{
		public void run()
		{
			try
			{
synchronized(loadlock)
{
				URLConnection c = resource.openConnection();

				// allocate memory
				//int size = c.getContentLength();
				//buffer = new byte[size+2];

				// download to memory
				InputStream is = c.getInputStream();
				ByteArrayOutputStream os = new ByteArrayOutputStream();

				while(true)
				{
					int b = is.read();
					if(b==-1) break;
					os.write(b);
				}

				buffer = os.toByteArray();
				os=null;
				System.gc();

				//find frame count
				AdvancedPlayer p = new AdvancedPlayer( new ByteArrayInputStream(buffer) );
				while(p.skipFrame()) max++;
}
				loading = false;
				runner = new Thread(me);
				runner.start();
			}
			catch(Exception e)
			{
				loading = false;
				buffer = null;
				title = "Error loading audio @ "+resource.toString();
				artist = "";

				e.printStackTrace();
			}
			finally
			{
				TrueMusicApplet.inst.check();
			}
		}
	}

	AdvancedPlayer p;

	volatile boolean pause = true;
	volatile int pos = 0;
	int current=0;
	int max = 0;

	public synchronized void play()
	{
		if(!pause) pos = 0;
		else
		{
			pause = false;
			notify();
		}
	}

	public synchronized void pause()
	{
		pause = !pause;
		if( !pause ) notify();
	}

	public synchronized void setPos(int npos)
	{	
		this.pos = npos;
	}

	public synchronized void stop()
	{
		pos = 0;
		pause = true;
		TrueMusicApplet.inst.prog.setValue(0);
	}

	public synchronized void dispose()
	{
		runner = null;
		buffer = null;
		p = null;
	}

	public void run()
	{
		while(true)
		{
			try
			{
				if(pause)
				{ 
					synchronized(this)
				 	{
                   			while(pause) wait();
           				}
				}

				synchronized(this)
				{
					if(p == null) p = new AdvancedPlayer( new ByteArrayInputStream(buffer) );

					try
					{
						javazoom.jl.player.JavaSoundAudioDevice.vol.setValue( TrueMusicApplet.inst.vol.getValue() );
					}
					catch(Exception e){}

					if(pos<current)
					{
						p = new AdvancedPlayer(new ByteArrayInputStream(buffer));
						current = 0;
					}

					boolean more=true;

					while(pos>current)
					{
						more = p.skipFrame();
						current++;
					}

					if(more)
					{
						more = p.decodeFrame();
						current++;
					}

					if(more) pos++;
					else 
					{
						pos = 0;
						pause = true;
						TrueMusicApplet.inst.next();
					}

					TrueMusicApplet.inst.prog.setMaximum(max);
					TrueMusicApplet.inst.prog.setValue(pos);
				}
			}
			catch(Exception e)
			{
				if(runner==null)return;
			}
		}
	}	


	public String toString()
	{
		if(loading) return "Loading "+title;
		return "\""+title +"\" by "+artist;
	}
}